﻿//////////////////////////////////////////////////////////////////////////////////
//
// Project            : ProxySwitch
// Module             : MainForm
// Description        : Mainform of the App.
// 
// Repository         : $URL$
// Last changed by    : $LastChangedBy$
// Revision           : $LastChangedRevision$
// Last Changed       : $LastChangedDate$
// Author             : $Author$
//
// Id                 : $Id$
//
// Copyright          : (c) 2010 Torsten Bär
//
// Published under the MIT License. See license.rtf or http://www.opensource.org/licenses/mit-license.php.
//
//////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using log4net;
using ProxySwitch.Properties;

namespace ProxySwitch
{
   /// <summary>
   /// Main dialog.
   /// </summary>
   public partial class MainForm : Form
   {
      private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

      /// <summary>
      /// Initializes a new instance of the <see cref="MainForm"/> class.
      /// </summary>
      public MainForm()
      {
         Log.Debug("Initializing components");

         InitializeComponent();

         Log.Debug("Initialized");
      }

      /// <summary>
      /// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event.
      /// </summary>
      /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
      protected override void OnLoad(EventArgs e)
      {
         Log.Debug("Loading last setting");

         if (!String.IsNullOrEmpty(Settings.Default.ProxySettings))
         {
            try
            {
               foreach (ProxySetting serializeableProxySetting in XmlSerializer<List<ProxySetting>>.Deserialize(Settings.Default.ProxySettings))
                  listViewProxy.Items.Add(new ProxyListViewItem(serializeableProxySetting));
            }
            catch (Exception exception)
            {
               Log.Error("Error loading settings", exception);
               MessageBox.Show(exception.Message, "Error loading settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            Log.DebugFormat("Initialized with {0} settings", listViewProxy.Items.Count);
         }
      }

      /// <summary>
      /// Handles the Click event of the button control.
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
      private void button_Click(object sender, EventArgs e)
      {
         if (Log.IsDebugEnabled)
         {
            Control control = sender as Control;
            Log.DebugFormat("Handling click event of {0}", control != null ? control.Name : "no control");
         }

         if (sender == buttonNew)
         {
            Log.Debug("Adding new Proxy");

            using (EditProxyForm editProxyForm = new EditProxyForm())
            {
               Log.Debug("Showing proxy edit form");

               if (editProxyForm.ShowDialog(this) == DialogResult.OK)
               {
                  Log.Debug("Proxy edir form successfully closed");

                  listViewProxy.Items.Add(new ProxyListViewItem(editProxyForm.Setting));
               }
               else
               {
                  Log.Debug("Proxy edit canceled");
               }
            }
         }
         else if(sender == buttonEdit)
         {
            Log.Debug("Editing current proxy setting");

            if(listViewProxy.SelectedItems != null)
            {
               ProxyListViewItem proxy = listViewProxy.SelectedItems.Cast<ProxyListViewItem>().FirstOrDefault();

               if(proxy != null)
               {
                  Log.DebugFormat("Current selected proxy is {0} {1} {2}", proxy.Setting.Address, proxy.Setting.Network, proxy.Setting.Bypass);

                  using (EditProxyForm proxyForm = new EditProxyForm(proxy.Setting))
                  {
                     Log.Debug("Opening edit form");

                     if(proxyForm.ShowDialog(this) == DialogResult.OK)
                     {
                        Log.Debug("Edit proxy finished");

                        proxy.UpdateSetting(proxyForm.Setting);
                     }
                     else
                     {
                        Log.Debug("Edit proxy canceled");
                     }
                  }
               }
            }
            else
            {
               Log.Debug("No setting selected");
            }
         }
         else if(sender == buttonDelete)
         {
            Log.Debug("Deleting selected setting");

            if(listViewProxy.SelectedItems != null)
            {
               ProxyListViewItem proxy = listViewProxy.SelectedItems
                  .Cast<ProxyListViewItem>()
                  .FirstOrDefault();

               if (proxy != null)
               {
                  Log.DebugFormat("Deleting setting {0} {1} {2}", proxy.Setting.Address, proxy.Setting.Network, proxy.Setting.Bypass);

                  listViewProxy.Items.Remove(proxy);
               }
            }
         }
         else if(sender == buttonApplyProxy)
         {
            Log.Debug("applying proxy");

            SetProxyToCurrentSelection();

            if (checkBoxAutoApply.Checked)
               ScheduleHelper.CreateSchedule();
            else
               ScheduleHelper.DisableSchedule();
         }
         else if (sender == buttonSaveApply || sender == buttonSave)
         {
            Log.Debug("Applying and saving setting");

            SaveCurrentSettings();

            if (sender == buttonSaveApply)
            {
               Log.Debug("Applying setting");

               Network.SetProxyForCurrentNetwork(listViewProxy.Items.Cast<ProxyListViewItem>().Where(item => item.Checked).Select(item => item.Setting));

               ShowBalloonTip();

               ScheduleHelper.CreateSchedule();
            }
         }

         Log.Debug("Event handled");
      }

      /// <summary>
      /// Raises the <see cref="E:System.Windows.Forms.Form.Closing"/> event.
      /// </summary>
      /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs"/> that contains the event data.</param>
      protected override void OnClosing(CancelEventArgs e)
      {
         Log.Debug("Form is closing");

         SaveCurrentSettings();
      }

      /// <summary>
      /// Handles the BalloonTipClosed event of the notifyIcon control.
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
      private void notifyIcon_BalloonTipClosed(object sender, EventArgs e)
      {
         notifyIcon.Visible = false;
      }

      /// <summary>
      /// Shows the ballon tip.
      /// </summary>
      private void ShowBalloonTip()
      {
         notifyIcon.Visible = true;
         notifyIcon.BalloonTipText = String.Format("Proxy {0}", Network.ProxyEnabled ? "set to " + Network.SystemProxy.Address : "disabled");
         notifyIcon.ShowBalloonTip((int)TimeSpan.FromSeconds(15).TotalMilliseconds);
      }

      /// <summary>
      /// Sets the proxy to current selection.
      /// </summary>
      private void SetProxyToCurrentSelection()
      {
         Log.Debug("Setting proxy to current selection");

         ProxyListViewItem selectedItem = listViewProxy.SelectedItems
            .Cast<ProxyListViewItem>()
            .FirstOrDefault();

         if (selectedItem != null)
         {
            SetProxy(selectedItem);
         }
         else
         {
            Log.Debug("No item selected");
         }
      }

      /// <summary>
      /// Sets the proxy.
      /// </summary>
      /// <param name="item">The item.</param>
      private void SetProxy(ProxyListViewItem item)
      {
         Log.DebugFormat("Setting proxy to {0} {1} {2}",
                         item.Setting.Address, item.Setting.Network, item.Setting.Bypass);

         Network.SetProxy(item.Setting);

         ShowBalloonTip();
      }

      /// <summary>
      /// Saves the current settings.
      /// </summary>
      private void SaveCurrentSettings()
      {
         Log.Debug("Saving current setting");

         string serialize = XmlSerializer<List<ProxySetting>>
            .Serialize(listViewProxy.Items
                              .Cast<ProxyListViewItem>()
                              .Select(item => item.Setting)
                              .ToList());

         Settings.Default.ProxySettings = serialize;
         Settings.Default.Save();

         Log.Debug("setting saved");
      }

      /// <summary>
      /// Handles the MouseDoubleClick event of the listViewProxy control.
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
      private void listViewProxy_MouseDoubleClick(object sender, MouseEventArgs e)
      {
         var item = listViewProxy.GetItemAt(e.Location.X, e.Location.Y);

         if (item != null)
         {
            var proxyListViewItem = item as ProxyListViewItem;
            if (proxyListViewItem != null)
               SetProxy(proxyListViewItem);
         }
      }
   }
}
